SUBDIRS = .

# stdlib directory
stdlibdir = $(datadir)/re2c/stdlib

# do not add compiler options/warnings here, add them in configure.ac
AM_CXXFLAGS = $(CXXFLAGSDEFAULT)
AM_CXXFLAGS += -DRE2C_STDLIB_DIR='"$(stdlibdir)/"'
if DEBUG
AM_CXXFLAGS += -DRE2C_DEBUG
endif

RE2CFLAGS = -br -W -Wno-match-empty-string

# binary
bin_PROGRAMS = re2c
noinst_PROGRAMS =

# sources
re2c_HDR = \
	src/constants.h \
	src/codegen/code.h \
	src/codegen/helpers.h \
	src/options/opt.h \
	src/options/symtab.h \
	src/adfa/adfa.h \
	src/cfg/cfg.h \
	src/dfa/closure_leftmost.h \
	src/dfa/closure_posix.h \
	src/dfa/determinization.h \
	src/dfa/dfa.h \
	src/dfa/posix_precedence.h \
	src/dfa/stacmd.h \
	src/dfa/tag_history.h \
	src/dfa/tagver_table.h \
	src/dfa/tcmd.h \
	src/nfa/nfa.h \
	src/encoding/case.h \
	src/encoding/ebcdic/ebcdic.h \
	src/encoding/ebcdic/ebcdic_regexp.h \
	src/encoding/enc.h \
	src/encoding/range_suffix.h \
	src/encoding/utf8/utf8.h \
	src/encoding/utf8/utf8_regexp.h \
	src/encoding/utf16/utf16_regexp.h \
	src/encoding/utf16/utf16.h \
	src/msg/location.h \
	src/msg/msg.h \
	src/msg/ver_to_vernum.h \
	src/msg/warn.h \
	src/regexp/re.h \
	src/regexp/rule.h \
	src/regexp/tag.h \
	src/compile.h \
	src/skeleton/mtag_trie.h \
	src/skeleton/path.h \
	src/skeleton/skeleton.h \
	src/parse/ast.h \
	src/parse/input.h \
	src/parse/parse.h \
	src/parse/scanner.h \
	src/parse/unescape.h \
	src/debug/debug.h \
	src/util/allocate.h \
	src/util/attribute.h \
	src/util/c99_stdint.h \
	src/util/file_utils.h \
	src/util/fixed_allocator.h \
	src/util/forbid_copy.h \
	src/util/free_list.h \
	src/util/hash32.h \
	src/util/local_increment.h \
	src/util/lookup.h \
	src/util/range.h \
	src/util/s_to_n32_unsafe.h \
	src/util/slab_allocator.h \
	src/util/smart_ptr.h \
	src/util/static_assert.h \
	src/util/string_utils.h \
	src/util/temp_file.h \
	src/util/u32lim.h \
	src/util/uniq_vector.h
re2c_SRC = \
	src/codegen/code_goto.cc \
	src/codegen/combine.cc \
	src/codegen/gen_bitmaps.cc \
	src/codegen/gen_delayed.cc \
	src/codegen/gen_dfa.cc \
	src/codegen/gen_goto.cc \
	src/codegen/gen_program.cc \
	src/codegen/gen_state.cc \
	src/codegen/helpers.cc \
	src/codegen/remove_empty.cc \
	src/codegen/render.cc \
	src/options/opt.cc \
	src/options/symtab.cc \
	src/nfa/estimate_size.cc \
	src/nfa/re_to_nfa.cc \
	src/adfa/adfa.cc \
	src/debug/dump_adfa.cc \
	src/debug/dump_cfg.cc \
	src/debug/dump_dfa.cc \
	src/debug/dump_dfa_tree.cc \
	src/debug/dump_interf.cc \
	src/debug/dump_nfa.cc \
	src/cfg/cfg.cc \
	src/cfg/compact.cc \
	src/cfg/dce.cc \
	src/cfg/freeze.cc \
	src/cfg/interfere.cc \
	src/cfg/liveanal.cc \
	src/cfg/normalize.cc \
	src/cfg/optimize.cc \
	src/cfg/rename.cc \
	src/cfg/varalloc.cc \
	src/dfa/closure.cc \
	src/dfa/dead_rules.cc \
	src/dfa/determinization.cc \
	src/dfa/fallback_tags.cc \
	src/dfa/fillpoints.cc \
	src/dfa/find_state.cc \
	src/dfa/minimization.cc \
	src/dfa/stacmd.cc \
	src/dfa/tagver_table.cc \
	src/dfa/tcmd.cc \
	src/encoding/ebcdic/ebcdic_regexp.cc \
	src/encoding/enc.cc \
	src/encoding/range_suffix.cc \
	src/encoding/utf8/utf8_regexp.cc \
	src/encoding/utf8/utf8.cc \
	src/encoding/utf16/utf16_regexp.cc \
	src/encoding/utf16/utf16.cc \
	src/msg/msg.cc \
	src/msg/warn.cc \
	src/regexp/ast_to_re.cc \
	src/regexp/default_tags.cc \
	src/regexp/fixed_tags.cc \
	src/regexp/nullable.cc \
	src/regexp/re.cc \
	src/regexp/rule.cc \
	src/regexp/split_charset.cc \
	src/regexp/tag.cc \
	src/compile.cc \
	src/skeleton/control_flow.cc \
	src/skeleton/generate_code.cc \
	src/skeleton/generate_data.cc \
	src/skeleton/maxpath.cc \
	src/skeleton/skeleton.cc \
	src/parse/ast.cc \
	src/parse/input.cc \
	src/parse/parse.cc \
	src/parse/scanner.cc \
	src/parse/unescape.cc \
	src/util/file_utils.cc \
	src/util/s_to_n32_unsafe.cc \
	src/util/temp_file.cc \
	src/util/range.cc
re2c_SOURCES = \
	src/main.cc \
	$(re2c_HDR) \
	$(re2c_SRC)

# autogenerated sources
re2c_GEN_HELP = src/msg/help.cc
re2c_GEN_LEX = src/parse/lex.cc
re2c_GEN_PARSER = src/parse/parser.cc
re2c_GEN_PARSER_HDR = src/parse/parser.h
re2c_GEN_VER_TO_VERNUM = src/msg/ver_to_vernum.cc
re2c_GEN_SRC = \
	$(re2c_GEN_HELP) \
	$(re2c_GEN_LEX) \
	$(re2c_GEN_PARSER) \
	$(re2c_GEN_VER_TO_VERNUM) \
	src/parse/lex_conf.cc \
	src/options/parse_opts.cc
re2c_GEN_HDR = \
	src/parse/lex.h \
	$(re2c_GEN_PARSER_HDR)
re2c_GEN = \
	$(re2c_GEN_SRC) \
	$(re2c_GEN_HDR)
nodist_re2c_SOURCES = $(re2c_GEN)

# custom rules create headers and must go before normal rules
BUILT_SOURCES = $(re2c_GEN_SRC)

# bootstrap sources
re2c_BOOT_PARSER = bootstrap/src/parse/parser.cc
re2c_BOOT_PARSER_HDR = bootstrap/src/parse/parser.h
re2c_BOOT_DOC_C = bootstrap/doc/re2c.1
re2c_BOOT_DOC_GO = bootstrap/doc/re2go.1
re2c_BOOT_DOC_RUST = bootstrap/doc/re2rust.1
re2c_BOOT_HELP = bootstrap/src/msg/help.cc
re2c_BOOT = \
	$(re2c_BOOT_DOC_C) \
	$(re2c_BOOT_DOC_GO) \
	$(re2c_BOOT_DOC_RUST) \
	$(re2c_BOOT_HELP) \
	$(re2c_BOOT_PARSER) \
	$(re2c_BOOT_PARSER_HDR) \
	bootstrap/src/parse/lex.cc \
	bootstrap/src/parse/lex.h \
	bootstrap/src/parse/lex_conf.cc \
	bootstrap/src/options/parse_opts.cc \
	bootstrap/src/msg/ver_to_vernum.cc

# custom sources
re2c_CUSTOM_PARSER = src/parse/parser.ypp
re2c_CUSTOM_HELP = doc/help.rst
re2c_CUSTOM = \
	$(re2c_CUSTOM_PARSER) \
	$(re2c_CUSTOM_HELP) \
	src/parse/lex.re \
	src/parse/lex_conf.re \
	src/options/parse_opts.re \
	src/msg/ver_to_vernum.re

# docs
re2c_SRC_DOC = doc/manpage.rst
re2c_SRC_DOC_EXT = \
	doc/manual/api/interface.rst_ \
	doc/manual/conditions/blocks.rst_ \
	doc/manual/conditions/conditions.rst_ \
	doc/manual/configurations/configurations.rst_ \
	doc/manual/directives/directives.rst_ \
	doc/manual/dot/dot.rst_ \
	doc/manual/encodings/encodings.rst_ \
	doc/manual/eof/01_sentinel.rst_ \
	doc/manual/eof/02_bounds_checking.rst_ \
	doc/manual/eof/03_eof_rule.rst_ \
	doc/manual/eof/04_generic_api.rst_ \
	doc/manual/eof/eof.rst_ \
	doc/manual/fill/01_fill.rst_ \
	doc/manual/fill/02_fill.rst_ \
	doc/manual/fill/fill.rst_ \
	doc/manual/headers/headers.rst_ \
	doc/manual/includes/includes.rst_ \
	doc/manual/options/debug.rst_ \
	doc/manual/options/internal.rst_ \
	doc/manual/options/options.rst_ \
	doc/manual/regexps/regular_expressions.rst_ \
	doc/manual/reuse/reuse.rst_ \
	doc/manual/skeleton/skeleton.rst_ \
	doc/manual/state/state.rst_ \
	doc/manual/submatch/submatch_example_mtags.rst_ \
	doc/manual/submatch/submatch_example_posix.rst_ \
	doc/manual/submatch/submatch_example_stags_fill.rst_ \
	doc/manual/submatch/submatch_example_stags.rst_ \
	doc/manual/submatch/submatch.rst_ \
	doc/manual/synopsis.rst_ \
	doc/manual/syntax/api1.rst_ \
	doc/manual/syntax/api2_c.rst_ \
	doc/manual/syntax/api2_go.rst_ \
	doc/manual/syntax/api2_rust.rst_ \
	doc/manual/syntax/api3.rst_ \
	doc/manual/syntax/intro.rst_ \
	doc/manual/syntax/syntax.rst_ \
	doc/manual/warnings/warnings_general.rst_ \
	doc/manual/warnings/warnings_list.rst_ \
	examples/c/01_basic.re \
	examples/c/01_basic.c \
	examples/c/conditions/parse_u32_blocks.re \
	examples/c/conditions/parse_u32_conditions.re \
	examples/c/encodings/unicode_identifier.re \
	examples/c/eof/01_sentinel.re \
	examples/c/eof/02_bounds_checking.re \
	examples/c/eof/03_eof_rule.re \
	examples/c/eof/05_generic_api_eof_rule.re \
	examples/c/fill/01_fill.re \
	examples/c/fill/02_fill.re \
	examples/c/headers/header.re \
	examples/c/headers/lexer/state.h \
	examples/c/includes/include.re \
	examples/c/includes/definitions.h \
	examples/c/reuse/reuse.re \
	examples/c/reuse/usedir.re \
	examples/c/state/push.re \
	examples/c/submatch/01_stags_fill.re \
	examples/c/submatch/01_stags.re \
	examples/c/submatch/02_mtags.re \
	examples/c/submatch/03_posix.re \
	examples/go/01_basic.re \
	examples/go/01_basic.go \
	examples/go/conditions/parse_u32_blocks.re \
	examples/go/conditions/parse_u32_conditions.re \
	examples/go/encodings/unicode_identifier.re \
	examples/go/eof/01_sentinel.re \
	examples/go/eof/02_bounds_checking.re \
	examples/go/eof/03_eof_rule.re \
	examples/go/eof/05_generic_api_eof_rule.re \
	examples/go/fill/01_fill.re \
	examples/go/fill/02_fill.re \
	examples/go/headers/header.re \
	examples/go/headers/lexer/state.go \
	examples/go/includes/include.re \
	examples/go/includes/definitions.go \
	examples/go/reuse/reuse.re \
	examples/go/reuse/usedir.re \
	examples/go/state/push.re \
	examples/go/submatch/01_stags_fill.re \
	examples/go/submatch/01_stags.re \
	examples/go/submatch/02_mtags.re \
	examples/go/submatch/03_posix.re \
	examples/rust/01_basic.re \
	examples/rust/01_basic.rs \
	examples/rust/conditions/parse_u32_blocks.re \
	examples/rust/conditions/parse_u32_conditions.re \
	examples/rust/encodings/unicode_identifier.re \
	examples/rust/eof/01_sentinel.re \
	examples/rust/eof/02_bounds_checking.re \
	examples/rust/eof/03_eof_rule.re \
	examples/rust/eof/05_generic_api_eof_rule.re \
	examples/rust/fill/01_fill.re \
	examples/rust/fill/02_fill.re \
	examples/rust/headers/header.re \
	examples/rust/headers/lexer/state.rs \
	examples/rust/includes/include.re \
	examples/rust/includes/definitions.rs \
	examples/rust/reuse/reuse.re \
	examples/rust/reuse/usedir.re \
	examples/rust/state/push.re \
	examples/rust/submatch/01_stags_fill.re \
	examples/rust/submatch/01_stags.re \
	examples/rust/submatch/02_mtags.re \
	examples/rust/submatch/03_posix.re

DOC_C = doc/re2c.1
DOCS = $(DOC_C)

if WITH_GOLANG
DOC_GO = doc/re2go.1
DOCS += $(DOC_GO)
endif

if WITH_RUST
DOC_RUST = doc/re2rust.1
DOCS += $(DOC_RUST)
endif

man_MANS = $(DOCS)

# include files (stdlib)
dist_stdlib_DATA = include/unicode_categories.re

CMAKEFILES := \
	CMakeLists.txt \
	cmake

EXTRA_DIST = \
	$(re2c_BOOT) \
	$(re2c_CUSTOM) \
	$(re2c_SRC_DOC_EXT) \
	$(CMAKEFILES) \
	CHANGELOG \
	LICENSE \
	NO_WARRANTY \
	README.md \
	autogen.sh \
	build \
	examples \
	test

CLEANFILES = \
	$(re2c_GEN) \
	$(DOCS)

if REBUILD_LEXERS
# generate lexer and update bootstrap files
.re.cc:
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)if test -x $(RE2C_FOR_BUILD); \
	then \
		$(RE2C_FOR_BUILD) $(RE2CFLAGS) -o $@ $< && \
		cp $(@:cc=[ch]*) $(top_srcdir)/bootstrap/$(@D); \
	else \
		echo "RE2C is not an executable file" && exit 1 ; \
	fi
else
# copy bootstrap files
.re.cc:
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)cp $(top_srcdir)/bootstrap/$(@:cc=*) $(@D)
	$(AM_V_at)echo "Reconfigure with --enable-lexers to regenerate $@"
endif

# cannot update bootstrap with distcheck (it makes srcdir readonly),
# so we update bootstrap only on incremental build (if re2c binary exists)
.ypp.cc:
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)if test $(BISON) = "no"; \
	then \
		cp $(top_srcdir)/bootstrap/$(@:cc=*) $(@D); \
	else \
		$(BISON) --output=$@ --defines=$(@:cc=h) $< && \
		if test -x $(top_builddir)/re2c$(EXEEXT); then \
			cp $@ $(@:cc=h) $(top_srcdir)/bootstrap/$(@D); \
		fi; \
	fi

# lexer depends on bison-generated header
$(re2c_GEN_LEX): $(re2c_GEN_PARSER)

# rebuild all re2c sources using newly built re2c
.PHONY: bootstrap
bootstrap: all
	rm $(re2c_GEN)
	$(MAKE) all

.PHONY: docs
if REBUILD_DOCS
docs: $(DOCS) $(re2c_GEN_HELP)
GENHELP = $(top_srcdir)/build/gen_help.sh
SPLITMAN = $(top_srcdir)/build/split_man.sh
# generate manpage for C
$(DOC_C): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).c c \
		&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).c > $@ \
		&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_C) \
		&& rm $(top_builddir)/$(re2c_SRC_DOC).c
# generate manpage for Go
$(DOC_GO): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).go go \
		&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).go > $@ \
		&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_GO) \
		&& rm $(top_builddir)/$(re2c_SRC_DOC).go
# generate manpage for Rust
$(DOC_RUST): $(re2c_SRC_DOC) $(re2c_SRC_DOC_EXT) $(SPLITMAN)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)$(SPLITMAN) $(top_builddir)/$(re2c_SRC_DOC) $(top_builddir)/$(re2c_SRC_DOC).rust rust \
		&& $(RST2MAN) --tab-width=4 $(top_builddir)/$(re2c_SRC_DOC).rust > $@ \
		&& cp $@ $(top_srcdir)/$(re2c_BOOT_DOC_RUST) \
		&& rm $(top_builddir)/$(re2c_SRC_DOC).rust
# generate help
$(re2c_GEN_HELP): $(re2c_CUSTOM_HELP) $(re2c_SRC_DOC_EXT) $(GENHELP)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)$(RST2MAN) $(top_builddir)/$(re2c_CUSTOM_HELP) > $@.1 \
		&& $(GENHELP) $@.1 $@ \
		&& cp $@ $(top_srcdir)/$(re2c_BOOT_HELP) \
		&& rm $@.1
else
docs: $(DOCS) $(re2c_GEN_HELP)
	$(AM_V_at)echo "Reconfigure with --enable-docs to rebuild docs"
# copy bootstrap manpage for C
$(DOC_C): $(re2c_BOOT_DOC_C)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_C) $@
# copy bootstrap manpage for Go
$(DOC_GO): $(re2c_BOOT_DOC_GO)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_GO) $@
# copy bootstrap manpage for Rust
$(DOC_RUST): $(re2c_BOOT_DOC_RUST)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_DOC_RUST) $@
# copy bootstrap help
$(re2c_GEN_HELP): $(re2c_BOOT_HELP)
	$(AM_V_at)$(MKDIR_P) $(@D)
	$(AM_V_GEN)cp $(top_srcdir)/$(re2c_BOOT_HELP) $@
endif

all-local: docs $(re2c_BOOT_PARSER)

# tests
re2c_TESTSUITE = run_tests.py
.PHONY: tests
tests: all $(re2c_TESTSUITE)
	$(top_builddir)/$(re2c_TESTSUITE)
.PHONY: vtests
vtests: all $(re2c_TESTSUITE)
	$(top_builddir)/$(re2c_TESTSUITE) --valgrind
.PHONY: wtests
wtests: all $(re2c_TESTSUITE)
	$(top_builddir)/$(re2c_TESTSUITE) --wine -j1

re2c_test_range_SOURCES = \
	src/test/range/test-impl.h \
	src/test/range/test.cc \
	src/test/range/test.h \
	src/util/range.cc\
	src/util/range.h \
	src/util/static_assert.h

re2c_test_s_to_n32_unsafe_SOURCES = \
	src/test/s_to_n32_unsafe/test.cc \
	src/util/s_to_n32_unsafe.cc

re2c_test_ver_to_vernum_SOURCES = \
	src/test/ver_to_vernum/test.cc \
	$(re2c_GEN_VER_TO_VERNUM)

re2c_test_argsubst_SOURCES = \
	src/test/argsubst/test.cc

check_PROGRAMS = \
	re2c_test_range \
	re2c_test_s_to_n32_unsafe \
	re2c_test_ver_to_vernum \
	re2c_test_argsubst

TESTS = \
	$(re2c_TESTSUITE) \
	$(check_PROGRAMS)

# benchmarks
if WITH_BENCHMARKS
SUBDIRS += benchmarks/submatch_dfa_aot
EXTRA_DIST += benchmarks/submatch_dfa_aot
endif

# libre2c
if WITH_LIBS
ACLOCAL_AMFLAGS = -I m4
lib_LTLIBRARIES =
include $(top_srcdir)/Makefile.lib.am
endif

# re2go
if WITH_GOLANG
bin_PROGRAMS += re2go
re2go_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=LANG_GO
re2go_SOURCES = $(re2c_SOURCES)
nodist_re2go_SOURCES = $(nodist_re2c_SOURCES)
endif

# re2rust
if WITH_RUST
bin_PROGRAMS += re2rust
re2rust_CXXFLAGS = $(AM_CXXFLAGS) -DRE2C_LANG=LANG_RUST
re2rust_SOURCES = $(re2c_SOURCES)
nodist_re2rust_SOURCES = $(nodist_re2c_SOURCES)
endif
